package com.zhang.spring.boot.mongo;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.util.ClassUtils;

import java.lang.annotation.Annotation;
import java.util.Set;

public class MongoRespRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false) {

            @Override
            protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                return beanDefinition.getMetadata().isIndependent()
                        && beanDefinition.getMetadata().isInterface()/*

                        && beanDefinition.getMetadata().hasAnnotatedMethods(SqlOperation.class.getName())*/;
            }
        };
//        scanner.addIncludeFilter(new AnnotationTypeFilter(MongoResp.class));
        scanner.addIncludeFilter(new AssignableTypeFilter(MongoRepository.class));
        String basePackage = ClassUtils.getPackageName(annotationMetadata.getClassName());
        StandardAnnotationMetadata ano=(StandardAnnotationMetadata)annotationMetadata;
        Class<?> startClazz=ano.getIntrospectedClass();
        EnableMongoResp annot=startClazz.getAnnotation(EnableMongoResp.class);
        Class<?> baseClazz=annot.repositoryFactoryBeanClass();

        Set<BeanDefinition> candidates = scanner.findCandidateComponents(basePackage);

        for (BeanDefinition candidate : candidates) {

            String candidateClassName = candidate.getBeanClassName();
            if (candidateClassName == null) {
                continue;
            }
            if(MongoRepository.class.getName().equals(candidateClassName)){
                continue;
            }

            Class candidateClass = ClassUtils.resolveClassName(candidateClassName, ClassUtils.getDefaultClassLoader());

            GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
            beanDefinition.setBeanClass(baseClazz);
            beanDefinition.getPropertyValues().add("mongoClient", new RuntimeBeanReference("mongoClient"));
            beanDefinition.getPropertyValues().add("type", candidateClass);

            beanDefinitionRegistry.registerBeanDefinition(candidateClassName, beanDefinition);
        }
    }
}
